'/
' MOTEP - Massive Online Text Environment Project
' --------------------------------------------------------------------------------
' MOTEP Client
' 
' GUI.bmx
' 
' (c) Anton Berlin. All Rights Reserved.
'/


include "LoadCommon.bmx"
include "..\Shared\LoadFonts.bmx"



'// Enumerators.
const MOUSE_POINTER_NORMAL:int = 0
const MOUSE_POINTER_LOADING:int = 1

const BUTTON_STATE_IDLE:int = 0
const BUTTON_STATE_PRESSING:int = 1
const BUTTON_STATE_PRESSED:int = 2

const FIELD_STATE_INACTIVE:int = 0
const FIELD_STATE_ACTIVE:int = 1

const CHECKBOX_STATE_UNCHECKED:int = 0
const CHECKBOX_STATE_CHECKED:int = 1



'// Font objects.
global defaultFont:TImageFont
global defaultFont2:TImageFont
global defaultFont3:TImageFont
global headline:TImageFont
global meterBar:TImageFont
global verdanaSmall:TImageFont
global verdanaMedium:TImageFont
global verdanaBig:TImageFont

'// Image object of the mouse pointers.
global mousePointer1:TImage = CreateImage(13, 20, 1)
global mousePointer1_Black:TImage = CreateImage(13, 20, 1)

'// How many frames that have passed the last second. Used to determine the FPS.
global framesThatHavePassed:int



'// Set masking color to magenta.
SetMaskColor(255, 0, 255)



'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		An interface is a container of layers, and the main object from which you controle the user interface and
'//		its gadgets. All methods in this type are public.
'// -----------------------------------------------------------------------------------------------------------------
type TInterface

	'// If this interface is visible, draw all the gadgets that are found in each visible layer. It returns 0 if the
	'// interface was invisible, and 1 if it actually drew something.
	method Draw:byte()
	
		if (m_invisible) return 0
		
		for local l:TLayer = eachin m_layers
		
			if (not l.m_visible) continue
			for local g:TWindow = eachin l.m_gadgets
			
				g.Draw()
			
			next
		
		next
		
		return 1
	
	end method
	
	'// Handle the input done to fields. If the current keystroke is writable, it adds it to curFieldInput:string
	'// in the currently active TTField (the active TTField is found in m_activeField). When enter is pressed, it
	'// sends the input to Master.InterfaceAction(), where an action is taken based on which gadget name was
	'// entered as the linked button. It returns 0 if there is no active field, otherwise 1.
	method HandleFieldInput:byte()
	
		if (not m_activeField) ..
			return 0
		
		if (m_activeField.m_state = FIELD_STATE_ACTIVE) then
		
			local currentKeyStroke:int = getKeyStroke()
			
			if (currentKeyStroke <> null) then
			
				if (currentKeyStroke = KEY_ESCAPE) then
				
					m_activeField.curFieldInput = null
					flushInput()
				
				else if (currentKeyStroke = KEY_BACKSPACE) then
				
					if (m_activeField.curFieldInput <> null) then
					
						m_activeField.curFieldInput = Mid(m_activeField.curFieldInput, 0, Len(m_activeField.curFieldInput))
						flushInput()
					
					end if
				
				else if (currentKeyStroke = KEY_ENTER) then
				
					if (m_activeField.m_layer.IsActive() and m_activeField.m_layer.IsVisible()) ..
						Master.InterfaceAction(m_activeField.m_linkedButton)
				
				else if (currentKeyStroke = KEY_TAB) then
				
					local next_g:TCrater = null
					local foundCurrent:byte = 0
					
					for local l:TLayer = eachin m_layers
					
						if (foundCurrent) ..
							exit
						
						for local g:TCrater = eachin l.m_gadgets
						
							if (foundCurrent = 1) then
							
								next_g = g
								next_g.m_state = FIELD_STATE_ACTIVE
								m_activeField = next_g
								exit
							
							end if
							
							if (g = m_activeField) ..
								foundCurrent = 1
							
							g.m_state = FIELD_STATE_INACTIVE
						
						next
					
					next
					
					'// If no field was found later in the list, use the first one added.
					if (next_g = null) then
					
						for local l:TLayer = eachin m_layers
						
							for local g:TCrater = eachin l.m_gadgets
							
								m_activeField = g
								g.m_state = FIELD_STATE_ACTIVE
								exit
							
							next
						
						next
					
					end if
				
				else if (writableKey(currentKeyStroke) = true) then
				
					m_activeField.curFieldInput = m_activeField.curFieldInput + Chr(currentKeyStroke)
					flushInput()
				
				end if
			end if
			
			m_activeField.m_text = m_activeField.curFieldInput
		
		end if
		
		return 1
	
	end method
	
	'// Clear all layers from gadgets.
	method ResetLayers()
	
		for local l:TLayer = eachin m_layers
			ClearList(l.m_gadgets); next
	
	end method
	
	'// Reset all gadgets in all layers, by deactivating them and setting their states to either inactive or idle.
	'// 		(byte) includeCheckboxes: Optional. Default value is false. Set this to true if you want to uncheck
	'//			all the checkboxes as well.
	method ResetInterfaceGadgets(includeCheckboxes:byte = false)
	
		for local l:TLayer = eachin m_layers
		
			l.m_active = 0
			
			for local g:TButton = eachin l.m_gadgets
				g.m_state = BUTTON_STATE_IDLE; next
			
			if (includeCheckboxes) then
			
				for local g:TCheckbox = eachin l.m_gadgets
					g.m_state = CHECKBOX_STATE_UNCHECKED; next
			
			end if
			
			for local g:TCrater = eachin l.m_gadgets
			
				g.m_state = FIELD_STATE_INACTIVE
				g.m_text = null
			
			next
		
		next
	
	end method
	
	'// Check if the mouse is hovering over any buttons, and if so, check if the left mouse button was pressed.
	'// If so, set the buttonstate to BUTTON_STATE_PRESSED and call Master.InterfaceAction() to execute its action.
	'// Returns 1 if the mouse was hovering over a button. Otherwise returns 0.
	method ActivateButton:byte()
	
		local tm:byte = false
		
		for local l:TLayer = eachin m_layers
		
			if (not l.IsActive()) ..
				continue
			if (not l.IsVisible()) ..
				continue
			
			for local g:TButton = eachin l.m_gadgets
			
				if (MouseX() > g.m_startX and MouseX() < g.m_endX and ..
				    MouseY() > g.m_startY and MouseY() < g.m_endY) then
				
					tm = true
					if (MouseDown(1)) then
					
						g.m_state = BUTTON_STATE_PRESSING
					
					else if (MouseHit(1)) then
					
						g.m_state = BUTTON_STATE_PRESSED
						Master.InterfaceAction(g.m_name) '// Depending on the name, execute appropreate action!
					
					else
						g.m_state = BUTTON_STATE_IDLE; end if
				
				else
					g.m_state = BUTTON_STATE_IDLE; end if
			
			next
		
		next
		
		'if (tm = false) ..
		'	return 0
		
		return tm
	
	end method
	
	'// Check if the mouse is hovering over any fields, and if so, check if the left mouse button was pressed. If
	'// so, set the active field (m_activeField) to that particular field. It also resets the states of all fields
	'// in that layer to FIELD_STATE_INACTIVE, except for the active one, whose state gets set to
	'// FIELD_STATE_ACTIVE. Returns 1 if the mouse was hovering over a field. Otherwise returns 0.
	method ActivateField:byte()
	
		local tm:byte = false
		local tc:TCrater = null
		
		for local l:TLayer = eachin m_layers
		
			if (tm) ..
				exit
			if (not l.IsActive()) ..
				continue
			if (not l.IsVisible()) ..
				continue
			
			for local g:TCrater = eachin l.m_gadgets
			
				if (MouseX() > g.m_startX and MouseX() < g.m_endX and ..
				    MouseY() > g.m_startY and MouseY() < g.m_endY) Then
				
					tm = True
					if (MouseHit(1)) ..					
						tc = g
					
					exit
				
				end if
			
			next
		
		next
		
		if (tm = false) ..
			return 0
		
		if (tc <> null) then
		
			for local l:TLayer = eachin m_layers
				for local g:TCrater = eachin l.m_gadgets
					g.m_state = FIELD_STATE_INACTIVE; next; next
			
			tc.m_state = FIELD_STATE_ACTIVE
			m_activeField = tc
		
		end if
		
		return 1
	
	end method
	
	'// Check if the mouse is hovering over any lists, and if so, check if the left mouse button was pressed. If
	'// so, set the selected item (gadget.m_selectedItem) to that particular item. Returns 1 if the mouse was
	'// hovering over an item. Otherwise returns 0.
	method ActivateItemList:byte()
	
		local tm:byte = false
		
		for local l:TLayer = eachin m_layers
		
			if (tm) ..
				exit
			if (not l.IsActive()) ..
				continue
			if (not l.IsVisible()) ..
				continue
			
			for local g:TItemList = eachin l.m_gadgets
			
				if (MouseX() > g.m_startX and MouseX() < g.m_endX) Then
				
					local row:int = 0
					for local i:String = eachin g.m_list
					
						if (g.m_list.First() = i) ..
							continue
						
						if (g.m_style = 0)
						
							if (MouseY() > g.m_startY + 2 + 14 * row and ..
							    MouseY() < g.m_startY + 2 + 14 * (row + 1)) then
							
								tm = True
								if (MouseHit(1)) ..
									g.m_selectedItem = row
								exit
							
							end if
						
						else if (g.m_style = 1)
						
							if (MouseY() > g.m_startY + 4 + 50 * row and ..
							    MouseY() < g.m_startY + 4 + 50 * (row + 1)) then
							
								tm = True
								if (MouseHit(1)) ..
									g.m_selectedItem = row
								exit
							
							end if
						
						end if
						
						row :+ 1
					
					next
				
				end if
			
			next
		
		next
		
		'if (tm = false) ..
		'	return 0
		
		return tm
	
	end method
	
	'// Check if the mouse is hovering over any checkboxes, and if so, check if the left mouse button was pressed.
	'// If so, set the active checkbox (m_activeCheckbox) to that particular checkbox. It also resets the states of
	'// all checkboxes in that layer to CHECKBOX_STATE_UNCHECKED, except for the active one, whose state gets set
	'// to CHECKBOX_STATE_CHECKED. Returns 1 if the mouse was hovering over a field. Otherwise returns 0.
	method ActivateCheckbox:byte()
	
		local tm:byte = false
		local tc:TCheckbox = null
		
		for local l:TLayer = eachin m_layers
		
			if (tm) ..
				exit
			if (not l.IsActive()) ..
				continue
			if (not l.IsVisible()) ..
				continue
			
			for local g:TCheckbox = eachin l.m_gadgets
			
				if (MouseX() > g.m_startX and MouseX() < g.m_endX and ..
				    MouseY() > g.m_startY and MouseY() < g.m_endY) then
				
					tm = true
					if (MouseHit(1)) ..
						tc = g
					exit
				
				end if
			
			next
		
		next
		
		if (tm = false) ..
			return 0
		
		if (tc <> null) then
		
			for local l:TLayer = eachin m_layers
				for local g:TCheckbox = eachin l.m_gadgets
					g.m_state = CHECKBOX_STATE_UNCHECKED; next; next
			
			tc.m_state = CHECKBOX_STATE_CHECKED
			m_activeCheckbox = tc
			Master.InterfaceAction(tc.m_name)
		
		end if
		
		return 1
	
	end method
	
	'// Select a specific field (TCrater) and set all fields in that layer to inactive, except for the selected one.
	'// Returns 1 if the field was found, otherwise 0.
	'//		(int) layer: The identifier of the layer where the field is contained.
	'//		(string) name: The identifier (in form of a name) of the field.
	method SelectField:byte(layer:int, name:string)
	
		if (not name) ..
			return 0
		
		local success:int = 0
		
		for local l:TLayer = eachin m_layers
		
			if (l.m_id <> layer) ..
				continue
			
			for local g:TCrater = eachin l.m_gadgets
			
				if (g.m_name = name) then
				
					g.m_state = FIELD_STATE_ACTIVE
					m_activeField = g
					success = 1
				
				else
					g.m_state = FIELD_STATE_INACTIVE; end if
			
			next
		
		next
		
		return success
	
	end method
	
	'// Select a specific checkbox and set all checkboxes in that layer to unchecked, except for the selected one.
	'// Returns 1 if the checkbox was found, otherwise 0.
	'//		(int) layer: The identifier of the layer where the checkbox is contained.
	'//		(string) name: The identifier (in form of a name) of the checkbox.
	method SelectCheckbox:byte(layer:int, name:string)
	
		if (not name) ..
			return 0
		
		local success:int = 0
		
		for local l:TLayer = eachin m_layers
		
			if (l.m_id <> layer) ..
				continue
			
			for local g:TCheckbox = eachin l.m_gadgets
			
				if (g.m_name = name) then
				
					g.m_state = CHECKBOX_STATE_CHECKED
					m_activeCheckbox = g
					success = 1
				
				else
					g.m_state = CHECKBOX_STATE_UNCHECKED; end if
			
			next
		
		next
		
		return success
	
	end method
	
	'// Add a column to a TItemList. Returns 1 if a column was added. Otherwise returns 0.
	'//		(string) name: The name of the listgadget.
	'//		(int) dataArgument: The argument of the data string (sepereated by ';' in the string) that should be
	'//			put in the column.
	'//		(int) xOffset: How many pixels from the g.m_startX the column should be drawn.
	method AddColumnToList:byte(name:string, dataArgument:int, xOffset:int)
	
		for local l:TLayer = eachin m_layers
		
			for local g:TItemList = eachin l.m_gadgets
			
				if (g.m_name = name) then
				
					for local c:int = 1 to 9
						if (g.m_columnDataArgument[c] <> 0) ..
							continue
						
						g.m_columnDataArgument[c] = dataArgument
						g.m_columnXOffset[c] = xOffset
						
						return 1
					
					next
				
				end if
			
			next
		
		next
		
		return 0
	
	end method
	
	'// Create a new TLayer and add it to the interface.
	'//		(int) layer_id: The prefered identifier of the new layer.
	'//		(byte) active: Whether or not the active should start out as active or not. It is inactive by default.
	method CreateLayer(layer_id:int, active:byte = false)
	
		local layerObject:TLayer = new TLayer
		layerObject.m_active = active
		layerObject.m_visible = 1
		layerObject.m_id = layer_id
		ListAddLast(m_layers, layerObject)
	
	end method
	
	'// Create a new TWindow and add it to the specified layer.
	'//		(int) layer: The identifier of the layer that the window should be contained in.
	'//		(string) name: The identifier of the window (in form of a name).
	'//		(int) sx: The position (on the X-axis) to start drawing the window.
	'//		(int) sy: The position (on the Y-axis) to start drawing the window.
	'//		(int) ex: The position (on the X-axis) to end drawing the window.
	'//		(int) ey: The position (on the Y-axis) to end drawing the window.
	method CreateWindow:byte(layer:int, name:string, sx:int, sy:int, ex:int, ey:int)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.CreateWindow(name, sx, sy, ex, ey)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Create a new TButton and add it to the specified layer.
	'//		(int) layer: The identifier of the layer that the button should be contained in.
	'//		(string) name: The identifier of the button (in form of a name).
	'//		(string) text: The text that should be drawn on the button.
	'//		(int) sx: The position (on the X-axis) to start drawing the button.
	'//		(int) sy: The position (on the Y-axis) to start drawing the button.
	'//		(int) ex: The position (on the X-axis) to end drawing the button.
	'//		(int) ey: The position (on the Y-axis) to end drawing the button.
	'//		(byte) crater: Optional parameter whose default value is true. It determines whether or not a "crater"
	'//			should be drawn around the button.
	method CreateButton:byte(layer:int, name:string, text:string, sx:int, sy:int, ex:int, ey:int, crater:byte = true)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.CreateButton(name, text, sx, sy, ex, ey, crater)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Create a new TText and add it to the specified layer.
	'//		(int) layer: The identifier of the layer that the text should be contained in.
	'//		(string) name: The identifier of the text (in form of a name).
	'//		(string) text: The actual text. Use $ to represent the newline character.
	'//		(int) sx: The position (on the X-axis) to start drawing the text.
	'//		(int) sy: The position (on the Y-axis) to start drawing the text.
	'//		(int) style: Optional parameter whose default value is 0. Set this to change the style of the text.
	'//			Set the style to 0 for regular text. Set the style to 1 for headlines.
	'//		(int) customRed: Optional parameter whose default value is -1. Set the custom red channel. -1 means
	'//			it's left to default.
	'//		(int) customGreen: Optional parameter whose default value is -1. Set the custom green channel. -1 
	'//			means it's left to default.
	'//		(int) customBlue: Optional parameter whose default value is -1. Set the custom blue channel. -1 means
	'//			it's left to default.
	method CreateText:byte(layer:int, name:string, text:string, sx:int, sy:int, style:int = 0, customRed:int = -1, customGreen:int = -1, customBlue:int = -1)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.CreateText(name, text, sx, sy, style)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Create a new TField and add it to the specified layer.
	'//		(int) layer: The identifier of the layer that the field should be contained in.
	'//		(string) name: The identifier of the field (in form of a name).
	'//		(int) sx: The position (on the X-axis) to start drawing the field.
	'//		(int) sy: The position (on the Y-axis) to start drawing the field.
	'//		(int) ex: The position (on the X-axis) to end drawing the field.
	'//		(int) ey: The position (on the Y-axis) to end drawing the field.
	'//		(string) linkedButton: The name of the button that the field is linked to. If enter would be pressed
	'//			while this field is active, it would call Master.InterfaceAction(linkedButton), to execute the
	'//			appropreate action.
	'//		(byte) isPass: Optional parameter whose default value is false. It determines whether or not the field
	'//			contains a password (in which case the text should be replaced visually with *'s).
	method CreateField:byte(layer:int, name:string, sx:int, sy:int, ex:int, ey:int, linkedButton:string, isPass:byte = false)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.CreateField(name, sx, sy, ex, ey, linkedButton, isPass)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Create a new TImg and add it to the specified layer.
	'//		(int) layer: The identifier of the layer that the image should be contained in.
	'//		(string) name: The identifier of the image (in form of a name).
	'//		(string) image: Url to the image that should be drawn.
	'//		(int) sx: The position (on the X-axis) to start drawing the image.
	'//		(int) sy: The position (on the Y-axis) to start drawing the image.
	'//		(int) width: Width of the image.
	'//		(int) height: Height of the image.
	'//		(byte) shading: Optional parameter whose default value is true. It determines whether or not the image
	'//			should have a shading effect around it (kind of like it would have a shadow below it).
	method CreateImg:byte(layer:int, name:string, image:string, sx:int, sy:int, width:int, height:int, shading:byte = true)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.CreateImg(name, image, sx, sy, width, height, shading)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Create a new TItemList and add it to the specified layer.
	'//		(int) layer: The identifier of the layer that the list should be contained in.
	'//		(string) name: The identifier of the list (in form of a name).
	'//		(TList) list: The list that should be shown graphically with this TItemList. Only string objects in
	'//			said list will be shown.
	'//		(int) sx: The position (on the X-axis) to start drawing the list.
	'//		(int) sy: The position (on the Y-axis) to start drawing the list.
	'//		(int) ex: The position (on the X-axis) to end drawing the list.
	'//		(int) ey: The position (on the Y-axis) to end drawing the list.
	'//		(int) columns: Optional parameter whose default value is 1. Specifies how many columns the list should
	'//			have. Remember that if the list should have more than one column, you have to add columns to it
	'//			with AddColumnToList(dataArgument:int, xOffset:int).
	'//		(int) style: Optional parameter whose default value is 0. Determines the style in which the list should
	'//			be drawn.
	method CreateItemList:byte(layer:int, name:string, list:TList, sx:int, sy:int, ex:int, ey:int, columns:int = 1, style:int = 0)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.CreateItemList(name, list, sx, sy, ex, ey, columns, style)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Create a new TCheckbox and add it to the specified layer.
	'//		(int) layer: The identifier of the layer that the checkbox should be contained in.
	'//		(string) name: The identifier of the checkbox (in form of a name).
	'//		(int) sx: The position (on the X-axis) to start drawing the checkbox.
	'//		(int) sy: The position (on the Y-axis) to start drawing the checkbox.
	method CreateCheckbox:byte(layer:int, name:string, sx:int, sy:int)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.CreateCheckbox(name, sx, sy)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Delete an existing TWindow from a layer.
	'//		(int) layer: The identifier of the layer that the window is contained in.
	'//		(string) name: The name of the window.
	method DeleteWindow:byte(layer:int, name:string)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.DeleteWindow(name)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Delete an existing TButton from a layer.
	'//		(int) layer: The identifier of the layer that the button is contained in.
	'//		(string) name: The name of the button.
	method DeleteButton:byte(layer:int, name:string)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.DeleteButton(name)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Delete an existing TTField from a layer.
	'//		(int) layer: The identifier of the layer that the field is contained in.
	'//		(string) name: The name of the field.
	method DeleteField:byte(layer:int, name:string)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.DeleteField(name)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Delete an existing TText from a layer.
	'//		(int) layer: The identifier of the layer that the text is contained in.
	'//		(string) name: The name of the text.
	method DeleteText:byte(layer:int, name:string)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.DeleteText(name)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Delete an existing TImg from a layer.
	'//		(int) layer: The identifier of the layer that the image is contained in.
	'//		(string) name: The name of the image.
	method DeleteImage:byte(layer:int, name:string)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.DeleteImage(name)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Delete an existing TCheckbox from a layer.
	'//		(int) layer: The identifier of the layer that the checkbox is contained in.
	'//		(string) name: The name of the checkbox.
	method DeleteCheckbox:byte(layer:int, name:string)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.DeleteCheckbox(name)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Delete an existing TItemList from a layer.
	'//		(int) layer: The identifier of the layer that the list is contained in.
	'//		(string) name: The name of the list.
	method DeleteItemList:byte(layer:int, name:string)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer) then
			
				l.DeleteItemList(name)
				return 1
			
			end if
		
		next
	
		return 0
	
	end method
	
	'// Access a specific TLayer.
	'//		(int) layer_id: The identifier of the layer to access.
	method AccessLayer:TLayer(layer_id:int)
	
		for local layer:TLayer = eachin m_layers
			
			if (layer.m_id = layer_id) ..
				return layer
			
		next
	
	end method
	
	'// Activate a specific TLayer.
	'//		(int) layer_id: The identifier of the layer to activate.
	method ActivateLayer:byte(layer_id:Int)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer_id) then
			
				l.ActivateLayer()
				return 1
			
			end if
		
		next
		
		return 0
	
	end method
	
	'// Dectivate a specific TLayer.
	'//		(int) layer_id: The identifier of the layer to deactivate.
	method DeactivateLayer:byte(layer_id:Int)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer_id) then
			
				l.DeactivateLayer()
				return 1
			
			end if
		
		next
		
		return 0
	
	end method
	
	'// Set the visibility of a specific TLayer.
	'//		(int) layer_id: The identifier of the layer.
	'//		(byte) state: The visibility state to set it to. True for visible and false for invisible. ;)
	method SetLayerVisibility:byte(layer_id:Int, state:byte)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer_id) then
			
				l.SetLayerVisibility(state)
				return 1
			
			end if
		
		next
		
		return 0
	
	end method
	
	'// Delete an existing TLayer from the interface.
	'//		(int) layer_id: The identifier of the layer to delete.
	method DeleteLayer:byte(layer_id:Int)
	
		for local l:TLayer = eachin m_layers
		
			if (l.m_id = layer_id) then
			
				m_layers.Remove(l)
				return 1
			
			end if
		
		next
		
		return 0
	
	end method
	
	'// List of layers contained in this interface.
	field m_layers:TList = new TList
	
	'// Set this flag to true if you don't want the interface to be drawn.
	field m_invisible:byte = false
	
	'// The currently active field (the active field is the field to which all keyboard input is getting sent)
	field m_activeField:TCrater = null
	
	'// The currently active checkbox.
	field m_activeCheckbox:TCheckbox = null

end type

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		This is the layer type, where all gadgets (windows, buttons, checkboxes, lists, images, etc) are loaded.
'// -----------------------------------------------------------------------------------------------------------------
type TLayer

	'// Check if this layer is active.
	method IsActive:byte(); return m_active; end method
	
	'// Check if this layer is visible.
	method IsVisible:byte(); return m_visible; end method
	
	'// Return the id of the layer.
	method GetLayerID:byte(); return m_id; end method
	
	'// Create a TWindow. How to use this is explained above.
	method CreateWindow(n:string, sx:int, sy:int, ex:int, ey:int)
	
		local windowObject:TWindow = new TWindow
		windowObject.m_startX = sx
		windowObject.m_startY = sy
		windowObject.m_endX = ex
		windowObject.m_endY = ey
		windowObject.m_name = n
		windowObject.m_layer = self
		ListAddLast(m_gadgets, windowObject)
	
	end method
	
	'// Create a TButton. How to use this is explained above.
	method CreateButton(n:string, t:string, sx:int, sy:int, ex:int, ey:int, c:byte = true)
	
		local buttonObject:TButton = new TButton
		buttonObject.m_startX = sx
		buttonObject.m_startY = sy
		buttonObject.m_endX = ex
		buttonObject.m_endY = ey
		buttonObject.m_text = t
		buttonObject.m_name = n
		buttonObject.m_state = BUTTON_STATE_IDLE
		buttonObject.m_crater = c
		buttonObject.m_layer = self
		ListAddLast(m_gadgets, buttonObject)
	
	end method
	
	'// Create a TText. How to use this is explained above.
	method CreateText(n:string, t:string, sx:int, sy:int, st:int= 0, cr:int = -1, cg:int = -1, cb:int = -1)
	
		local textObject:TText = new TText
		textObject.m_startX = sx
		textObject.m_startY = sy
		textObject.m_name = n
		textObject.m_text = t
		textObject.m_style = st
		textObject.m_layer = self
		textObject.m_customColorR = cr
		textObject.m_customColorG = cg
		textObject.m_customColorB = cb
		ListAddLast(m_gadgets, textObject)
	
	end method
	
	'// Create a field (TCrater). How to use this is explained above.
	method CreateField(n:string, sx:int, sy:int, ex:int, ey:int, linkedButton:string, pass:byte = false)
	
		local fieldObject:TCrater = new TCrater
		fieldObject.m_startX = sx
		fieldObject.m_startY = sy
		fieldObject.m_endX = ex
		fieldObject.m_endY = ey
		fieldObject.m_name = n
		fieldObject.m_state = FIELD_STATE_INACTIVE
		fieldObject.m_containsPassword = pass
		fieldObject.m_linkedButton = linkedButton
		fieldObject.m_layer = self
		ListAddLast(m_gadgets, fieldObject)
	
	end method
	
	'// Create a TImg. How to use this is explained above.
	method CreateImg(n:string, i:string, sx:int, sy:int, ex:int, ey:int, shading:byte = true)
	
		local imageObject:TImg = new TImg
		imageObject.m_startX = sx
		imageObject.m_startY = sy
		imageObject.m_endX = ex
		imageObject.m_endY = ey
		imageObject.m_name = n
		imageObject.m_image = i
		imageObject.m_shading = shading
		imageObject.m_layer = self
		ListAddLast(m_gadgets, imageObject)
	
	end method
	
	'// Create a TCheckbox. How to use this is explained above.
	method CreateCheckbox(n:string, sx:int, sy:int, state:int = CHECKBOX_STATE_UNCHECKED)
	
		local checkboxObject:TCheckbox = new TCheckbox
		checkboxObject.m_startX = sx
		checkboxObject.m_startY = sy
		checkboxObject.m_endX = sx + 18
		checkboxObject.m_endY = sy + 18
		checkboxObject.m_name = n
		checkboxObject.m_state = state
		checkboxObject.m_layer = self
		ListAddLast(m_gadgets, checkboxObject)
	
	end method
	
	'// Create a list (TItemList). How to use this is explained above.
	method CreateItemList(n:string, lst:TList, sx:int, sy:int, ex:int, ey:int, c:int = 1, st:int = 0)
	
		local listObject:TItemList = new TItemList
		listObject.m_startX = sx
		listObject.m_startY = sy
		listObject.m_endX = ex
		listObject.m_endY = ey
		listObject.m_name = n
		listObject.m_list = lst
		listObject.m_columns = c
		listObject.m_layer = self
		listObject.m_style = st
		ListAddLast(m_gadgets, listObject)
	
	end method
	
	'// Delete a TWindow. How to use this is explained above.
	method DeleteWindow:byte(n:string)
	
		for local g:TWindow = eachin m_gadgets
		
			if (g.m_name = n) then
			
				m_gadgets.Remove(g)
				return 1
			
			end if
		
		next
		
		return 0
	
	end method
	
	'// Delete a TButton. How to use this is explained above.
	method DeleteButton:byte(n:string)
	
		for local g:TButton = eachin m_gadgets
		
			if (g.m_name = n) then
			
				m_gadgets.Remove(g)
				return 1
			
			end if
		
		next
		
		return 0
	
	end method
	
	'// Delete a field (TCrater). How to use this is explained above.
	method DeleteField:byte(n:string)
	
		for local g:TCrater = eachin m_gadgets
		
			if (g.m_name = n) then
			
				m_gadgets.Remove(g)
				return 1
			
			end if
		
		next
		
		return 0
	
	end method
	
	'// Delete a TText. How to use this is explained above.
	method DeleteText:byte(n:string)
	
		for local g:TText = eachin m_gadgets
		
			if (g.m_name = n) then
			
				m_gadgets.Remove(g)
				return 1
			
			end if
		
		next
		
		return 0
	
	end method
	
	'// Delete a TImg. How to use this is explained above.
	method DeleteImage:byte(n:string)
	
		for local g:TImg = eachin m_gadgets
		
			if (g.m_name = n) then
			
				m_gadgets.Remove(g)
				return 1
			
			end if
		
		next
		
		return 0
	
	end method
	
	'// Delete a TCheckbox. How to use this is explained above.
	method DeleteCheckbox:byte(n:string)
	
		for local g:TCheckbox = eachin m_gadgets
		
			if (g.m_name = n) then
			
				m_gadgets.Remove(g)
				return 1
			
			end if
		
		next
		
		return 0
	
	end method
	
	'// Delete a TItemList. How to use this is explained above.
	method DeleteItemList:byte(n:string)
	
		for local g:TItemList = eachin m_gadgets
		
			if (g.m_name = n) then
			
				m_gadgets.Remove(g)
				return 1
			
			end if
		
		next
		
		return 0
	
	end method
	
	'// Activate the layer. How to use this is explained above.
	method ActivateLayer(); m_active = 1; end method
	
	'// Deactivate the layer. How to use this is explained above.
	method DeactivateLayer(); m_active = 0; end method
	
	'// Set the layer visibility. How to use this is explained above.
	method SetLayerVisibility(v:byte); m_visible = v; end method
	
	'// Clears the gadgetlist and thus destroys all gadgets contained inside of this layer.
	method DestroyGadgets(); ClearList(m_gadgets); end method
	
	'// List of gadgets contained inside of this layer.
	field m_gadgets:TList = new TList
	
	'// Set this flag to false if you don't want the user to be able to interact with it's gadgets.
	field m_active:byte
	
	'// Set this flag to false if you don't want the gadgets contained in the layer to be drawn.
	field m_visible:byte
	
	'// The identifier of the layer.
	field m_id:int

end type

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		This type is for creating a window.
'// -----------------------------------------------------------------------------------------------------------------
type TWindow

	'// Set the name of the gadget.
	'//		(string) name: The name (identifier) to give the gadget.
	method SetName(name:string); m_name = name; end method
	
	'// Return the name of the gadget.
	method GetName:string(); return m_name; end method
	
	'// Draw the window.
	method Draw:byte()
	
		'// Check if the settings of this TWindow are invalid or not.
		if (m_startX > m_endX or m_startY > m_endY) ..
			return 0
		
		'// Declare some needed variables.
		local oldr:int, oldg:int, oldb:int
		
		'// Set width and length.
		local width:int = m_endX - m_startX
		local height:int = m_endY - m_startY
		
		'// Reset font to default font.
		SetImageFont(defaultFont)
		
		'// Save old colors and set current color to brown.
		clrBrown()
		oldr = oldColorR
		oldg = oldColorG
		oldb = oldColorB
		
		'// Draw the window.
						DrawRect(m_startX + 2, m_startY + 2, width - 4, height - 4) '// Filling
		clrBrightBrown();	DrawLine(m_startX, m_startY, m_startX, m_endY - 1) '// Left margin
						DrawLine(m_startX + 1, m_startY, m_startX + 1, m_endY - 2) '// Left margin
		 				DrawLine(m_startX, m_startY, m_endX - 1, m_startY) '// Upper margin
		  				DrawLine(m_startX, m_startY + 1, m_endX - 2, m_startY + 1) '// Upper margin
		clrDarkBrown();	DrawLine(m_endX - 1, m_startY + 1, m_endX - 1, m_endY - 1) '// Right margin
						DrawLine(m_endX - 2, m_startY + 2, m_endX - 2, m_endY - 2) '// Right margin
						DrawLine(m_startX + 2, m_endY - 2, m_endX - 1, m_endY - 2) '// Lower margin
						DrawLine(m_startX + 1, m_endY - 1, m_endX - 1, m_endY - 1) '// Lower margin
						
		'// Draw the shading effect.
		rectShadingFX(m_startX, m_startY, m_endX, m_endY)
		
		'// Reset to old colors.
		clrCustom(oldr, oldg, oldb)
	
	end method
	
	'// Global function for drawing the shading effect.
	function rectShadingFX(sx:int, sy:int, ex:int, ey:int)
	
		clrBlack()
		
		SetAlpha(0.05);	DrawLine(sx - 6, sy - 6, sx - 6, ey + 4, false) '// Left
						DrawLine(ex + 5, sy - 5, ex + 5, ey + 5, false) '// Right
						DrawLine(sx - 5, sy - 6, ex + 5, sy - 6, false) '// Upper
						DrawLine(sx - 6, ey + 5, ex + 4, ey + 5, false) '// Lower
		SetAlpha(0.10);	DrawLine(sx - 5, sy - 5, sx - 5, ey + 3, false)
						DrawLine(ex + 4, sy - 4, ex + 4, ey + 4, false)
						DrawLine(sx - 4, sy - 5, ex + 4, sy - 5, false)
						DrawLine(sx - 5, ey + 4, ex + 3, ey + 4, false)
		SetAlpha(0.20);	DrawLine(sx - 4, sy - 4, sx - 4, ey + 2, false)
						DrawLine(ex + 3, sy - 3, ex + 3, ey + 3, false)
						DrawLine(sx - 3, sy - 4, ex + 3, sy - 4, false)
						DrawLine(sx - 4, ey + 3, ex + 2, ey + 3, false)
		SetAlpha(0.30);	DrawLine(ex + 2, sy - 2, ex + 2, ey + 2, false)
						DrawLine(sx - 3, sy - 3, sx - 3, ey + 1, false)
						DrawLine(sx - 2, sy - 3, ex + 2, sy - 3, false)
						DrawLine(sx - 3, ey + 2, ex + 1, ey + 2, false)
		SetAlpha(0.50);	DrawLine(sx - 2, sy - 2, sx - 2, ey + 0, false)
						DrawLine(ex + 1, sy - 1, ex + 1, ey + 1, false)
						DrawLine(sx - 1, sy - 2, ex + 1, sy - 2, false)
						DrawLine(sx - 2, ey + 1, ex + 0, ey + 1, false)
		SetAlpha(0.75);	DrawLine(sx - 1, sy - 1, sx - 1, ey - 1, false)
						DrawLine(ex + 0, sy - 0, ex + 0, ey + 0, false)
						DrawLine(sx - 0, sy - 1, ex + 0, sy - 1, false)
						DrawLine(sx - 1, ey + 0, ex - 1, ey + 0, false)
		
		SetAlpha(1.00) '// Reset alpha.
	
	end function
	
	'// Specifies the size of the gadget.
	field m_startX:int
	field m_startY:int
	field m_endX:int
	field m_endY:int
	
	'// The identifier of this gadget (in form of a name).
	field m_name:string
	
	'// The layer that this gadget belongs to.
	field m_layer:TLayer

end type

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		This is for creating a button.
'// -----------------------------------------------------------------------------------------------------------------
type TButton extends TWindow

	'// Set the state of the button.
	'// 		(int) state: The new state of the button.
	method SetState(state:int); m_state = state; end method
	
	'// Return the current state of the button.
	method GetState:int(); return m_state; end method
	
	'// Draw the button.
	method Draw:byte()
	
		'// Check if the settings of this TWindow are invalid or not.
		if (m_startX > m_endX or m_startY > m_endY) ..
			return 0
		
		'// Declare some needed variables.
		local oldr:int, oldg:int, oldb:int
		
		'// Set width and length.
		local width:int = m_endX - m_startX
		local height:int = m_endY - m_startY
		
		'// Reset font to default font.
		SetImageFont(defaultFont)
		
		'// Save old colors and set current color to dark brown.
		clrDarkBrown()
		oldr = oldColorR
		oldg = oldColorG
		oldb = oldColorB
		
		'// Draw the "crater" or the shading effect surrounding the button.
		if (m_crater) then
		
							DrawLine(m_startX - 2, m_startY - 2, m_startX - 2, m_endY + 1) '// Left margin
							DrawLine(m_startX - 1, m_startY - 2, m_startX - 1, m_endY) '// Left margin
		 					DrawLine(m_startX - 2, m_startY - 2, m_endX + 1,   m_startY - 2) '// Upper margin
		  					DrawLine(m_startX - 2, m_startY - 1, m_endX,       m_startY - 1) '// Upper margin
			clrBrightBrown();	DrawLine(m_endX + 1,   m_startY - 1, m_endX + 1,   m_endY + 1) '// Right margin
							DrawLine(m_endX,       m_startY,     m_endX,       m_endY) '// Right margin
							DrawLine(m_startX,     m_endY,       m_endX,       m_endY) '// Lower margin
							DrawLine(m_startX - 1, m_endY + 1,   m_endX + 1,   m_endY + 1) '// Lower margin
		
		else
		
			'// Draw the shading effect.
			rectShadingFX(m_startX, m_startY, m_endX, m_endY)
		
		end if
		
		'// Draw the button.
		select (m_state)
		
			case BUTTON_STATE_PRESSING, BUTTON_STATE_PRESSED
				clrCustom(45, 70, 180)	DrawRect(m_startX + 2, m_startY + 2, width - 4,    height - 4) '// Filling
				clrCustom(30, 45, 120)	DrawLine(m_startX,     m_startY,     m_startX,     m_endY - 1) '// Left margin
									DrawLine(m_startX + 1, m_startY,     m_startX + 1, m_endY - 2) '// Left margin
		 							DrawLine(m_startX,     m_startY,     m_endX - 1,   m_startY) '// Upper margin
		  							DrawLine(m_startX,     m_startY + 1, m_endX - 2,   m_startY + 1) '// Upper margin
				clrCustom(75, 100, 210)	DrawLine(m_endX - 1,   m_startY + 1, m_endX - 1,   m_endY - 1) '// Right margin
									DrawLine(m_endX - 2,   m_startY + 2, m_endX - 2,   m_endY - 2) '// Right margin
									DrawLine(m_startX + 2, m_endY - 2,   m_endX - 1,   m_endY - 2) '// Lower margin
									DrawLine(m_startX + 1, m_endY - 1,   m_endX - 1,   m_endY - 1) '// Lower margin
									DrawLine(m_startX + 1, m_endY - 1,   m_endX - 1,   m_endY - 1) '// Lower margin
				'// Draw the button text.
				'clrDarkBlue()
				local tx:int = (m_startX + m_endX) / 2 - Len(m_text) * 3 + 1
				local ty:int = (m_startY + m_endY) / 2 - 7
				local tempText:TText = new TText
				tempText.m_text = self.m_text
				tempText.m_startX = tx
				tempText.m_startY = ty
				tempText.Draw()
			default
				clrCustom(45, 70, 180)	DrawRect(m_startX + 2, m_startY + 2, width - 4,    height - 4) '// Filling
				clrCustom(75, 100, 210)	DrawLine(m_startX,     m_startY,     m_startX,     m_endY - 1) '// Left margin
									DrawLine(m_startX + 1, m_startY,     m_startX + 1, m_endY - 2) '// Left margin
		 							DrawLine(m_startX,     m_startY,     m_endX - 1,   m_startY) '// Upper margin
		  							DrawLine(m_startX,     m_startY + 1, m_endX - 2,   m_startY + 1) '// Upper margin
				clrCustom(30, 45, 120)	DrawLine(m_endX - 1,   m_startY + 1, m_endX - 1,   m_endY - 1) '// Right margin
									DrawLine(m_endX - 2,   m_startY + 2, m_endX - 2,   m_endY - 2) '// Right margin
									DrawLine(m_startX + 2, m_endY - 2,   m_endX - 1,   m_endY - 2) '// Lower margin
									DrawLine(m_startX + 1, m_endY - 1,   m_endX - 1,   m_endY - 1) '// Lower margin
				'// Draw the button text.
				local tx:int = (m_startX + m_endX) / 2 - Len(m_text) * 3
				local ty:int = (m_startY + m_endY) / 2 - 8
				local tempText:TText = new TText
				tempText.m_text = self.m_text
				tempText.m_startX = tx
				tempText.m_startY = ty
				tempText.Draw()
		
		end select
		
		'// Reset to old colors.
		clrCustom(oldr, oldg, oldb)
	
	end method
	
	'// The state of the button. It can be one of the following:
	'//		BUTTON_STATE_IDLE = The button is not being used in any way.
	'//		BUTTON_STATE_PRESSING = The button is being pressed.
	'//		BUTTON_STATE_PRESSED = The button has been pressed.
	field m_state:int
	
	'// Text to draw on the button, that describes the action the button does.
	field m_text:string
	
	'// Whether or not to draw a "crater" around the button.
	field m_crater:byte = true

end type

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		This is for creating fields (craters).
'// -----------------------------------------------------------------------------------------------------------------
type TCrater extends TWindow

'*** public:

	'// Set the state of the field.
	'// 		(int) state: The new state of the field.
	method SetState(state:int); m_state = state; end method
	
	'// Return the current state of the field.
	method GetState:int(); return m_state; end method
	
	'// Set the text that the field contains.
	'//		(string) text: The new text string.
	method SetText(text:string); m_text = text; end method
	
	'// Return the text that the field currently contains.
	method GetText:string(); return m_text; end method
	
	'// Draw the field.
	method Draw:byte()
	
		' Check if the settings of this TWindow are invalid or not.
		if (m_startX > m_endX or m_startY > m_endY) ..
			return 0
		
		' Declare some needed variables.
		local oldr:int, oldg:int, oldb:int
		
		' Set width and length.
		local width:int = m_endX - m_startX
		local height:int = m_endY - m_startY
		
		' Reset font to default font.
		SetImageFont(defaultFont)
		
		' Save old colors and set current color to brown.
		if (m_state = FIELD_STATE_INACTIVE) then
		
			clrDarkerBrown()
		
		else if (m_state = FIELD_STATE_ACTIVE) then
		
			clrMediumBrown()
		
		end if
		oldr = oldColorR
		oldg = oldColorG
		oldb = oldColorB
		
		' Draw the field.
						DrawRect(m_startX + 2, m_startY + 2, width - 4, height - 4) '// Filling
		clrDarkBrown();	DrawLine(m_startX, m_startY, m_startX, m_endY - 1) '// Left margin
						DrawLine(m_startX + 1, m_startY, m_startX + 1, m_endY - 2) '// Left margin
		 				DrawLine(m_startX, m_startY, m_endX - 1, m_startY) '// Upper margin
		  				DrawLine(m_startX, m_startY + 1, m_endX - 2, m_startY + 1) '// Upper margin
		clrBrightBrown();	DrawLine(m_endX - 1, m_startY + 1, m_endX - 1, m_endY - 1) '// Right margin
						DrawLine(m_endX - 2, m_startY + 2, m_endX - 2, m_endY - 2) '// Right margin
						DrawLine(m_startX + 2, m_endY - 2, m_endX - 1, m_endY - 2) '// Lower margin
						DrawLine(m_startX + 1, m_endY - 1, m_endX - 1, m_endY - 1) '// Lower margin
		
		' Draw the input text
		if (not m_containsPassword) then
		
			local tempText:TText = new TText
			tempText.m_text = self.m_text
			tempText.m_startX = self.m_startX + 6
			tempText.m_startY = self.m_startY + 2
			tempText.Draw()
		
		else
		
			local tempText:TText = new TText
			local hiddenText:string = null
			for local c:int = 1 to Len(m_text)
				hiddenText = hiddenText + "*"
			next
			tempText.m_text = hiddenText
			tempText.m_startX = self.m_startX + 6
			tempText.m_startY = self.m_startY + 2
			tempText.Draw()
		
		end if
		
		' Reset to old colors
		clrCustom(oldr, oldg, oldb)
	
	end method
	
	'// The state of the field. It can be one of the following:
	'//		FIELD_STATE_ACTIVE = The field is active.
	'//		FIELD_STATE_INACTIVE = The field is not active.
	field m_state:int
	
	'// The text that the field contains at the moment (through keyboard input).
	field m_text:string = null
	
	'// Set this flag to true if this field contains a password. It changes all characters to '*' visually.
	field m_containsPassword:byte = false
	
	'// The button this field is linked to. This button will be pressed if this field is active, the layer it is
	'// contained in is active, and the enter key is pressed.
	field m_linkedButton:string

'*** private:

	'// Current input to the field.
	field curFieldInput:string

end type

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		This is for creating text.
'// -----------------------------------------------------------------------------------------------------------------
type TText extends TWindow

	'// Set the text that the TText object should print.
	'//		(string) text: The text the TText object should print. Use $ to represent the newline character.
	method SetText(text:string); m_text = text; end method
	
	'// Return the text that the TText object contains.
	method GetText:string(); return m_text; end method

	'// Set custom text color (overrides the default colors of the text-styles).
	'//		(int) red: Red channel (0-255)
	'//		(int) green: Green channel (0-255)
	'//		(int) blue: Blue channel (0-255)
	method SetCustomColor(red:int, green:int, blue:int)
	
		m_customColorR = red
		m_customColorG = green
		m_customColorB = blue
	
	end method
	
	'// Draw the text.
	method Draw:byte()
	
		'// Declare some needed variables.
		local oldr:int, oldg:int, oldb:int, curX:int, curY:int
		
		'// Save old colors and set current color to dark brown.
		clrBlack()
		oldr = oldColorR
		oldg = oldColorG
		oldb = oldColorB
		
		'// Draw the text.
		if (str.words(m_text, KEY_DOLLAR) - 1) then
		
			curX = m_startX
			curY = m_startY
			
			for local i:int = 0 until str.words(m_text, KEY_DOLLAR)
			
				local line:string = str.word(i, m_text, KEY_DOLLAR)
				if (m_style = 0) then
				
					'// Reset font to default font.
					SetImageFont(defaultFont)
					
					'// Black outlining.
					clrBlack()
					DrawText(line, curX - 1, curY - 1)
					DrawText(line, curX + 1, curY + 1)
					
					'// Shading effect.
					SetAlpha(0.5)
					DrawText(line, curX + 2, curY + 2)
					SetAlpha(1.0)
					
					'// Filling.
					if (m_customColorR = -1) ..
						clrCommon() ..
					else ..
						clrCustom(m_customColorR, m_customColorG, m_customColorB)
					DrawText(line, curX, curY)
					
					'// Move the next line of text downwards one line (14 pixels).
					curY :+ 14
				
				else if (m_style = 1) then
				
					'// Reset font to default font.
					SetImageFont(headline)
					
					'// Black outlining.
					clrBlack()
					DrawText(line, curX - 1, curY - 1)
					DrawText(line, curX + 1, curY + 1)
					
					'// Shading effect.
					SetAlpha(0.5)
					DrawText(line, curX + 2, curY + 2)
					SetAlpha(1.0)
					
					'// Filling.
					if (m_customColorR = -1) ..
						clrHeadline() ..
					else ..
						clrCustom(m_customColorR, m_customColorG, m_customColorB)
					DrawText(line, curX, curY)
					
					'// Move the next line of text downwards one line (16 pixels).
					curY :+ 16
				
				end if
			
			next
		
		else
		
			if (m_style = 0) then
			
				'// Reset font to default font.
				SetImageFont(defaultFont)
				
				'// Black outlining.
				clrBlack()
				DrawText(m_text, m_startX - 1, m_startY - 1)
				DrawText(m_text, m_startX + 1, m_startY + 1)
				
				'// Shading effect.
				SetAlpha(0.5)
				DrawText(m_text, m_startX + 2, m_startY + 2)
				SetAlpha(1.0)
				
				'// Filling.
				if (m_customColorR = -1) ..
					clrCommon() ..
				else ..
					clrCustom(m_customColorR, m_customColorG, m_customColorB)
				
				DrawText(m_text, m_startX, m_startY)
			
			else if (m_style = 1) then
			
				'// Reset font to default font.
				SetImageFont(headline)
				
				'// Black outlining.
				clrBlack()
				DrawText(m_text, m_startX - 1, m_startY - 1)
				DrawText(m_text, m_startX + 1, m_startY + 1)
				
				'// Shading effect.
				SetAlpha(0.5)
				DrawText(m_text, m_startX + 2, m_startY + 2)
				SetAlpha(1.0)
				
				'// Filling.
				if (m_customColorR = -1) ..
					clrHeadline() ..
				else ..
					clrCustom(m_customColorR, m_customColorG, m_customColorB)
				DrawText(m_text, m_startX, m_startY)
			
			end if
		
		end if
		
		'// Reset to old colors.
		clrCustom(oldr, oldg, oldb)
	
	end method
	
	'// The text the object contains.
	field m_text:string
	
	'// Custom color. This is optional, since the "styles" all have default colors.
	field m_customColorR:int = -1, m_customColorG:int = -1, m_customColorB:int = -1
	
	'// The style of the text. It can be one of the following:
	'//		0 = Regular text.
	'//		1 = Headline.
	field m_style:int

end type

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		This is for creating text.
'// -----------------------------------------------------------------------------------------------------------------
type TImg extends TWindow

	'// Set the url to the image to draw.
	'//		(string) image: The url to the image.
	method SetImage(image:string); m_image = image; end method
	
	'// Return the url of the image.
	method GetImage:string(); return m_image; end method
	
	'// Draw the image.
	method Draw:byte()
	
		'// Draw the image - m_endX and m_endY = width and height here.
		local image:TImage = CreateImage(m_endX, m_endY, 1)
		image = LoadImage(m_image)
		DrawImage(image, m_startX, m_startY)
		
		'// Shading effect.
		if (m_shading) ..
			rectShadingFX(m_startX, m_startY, m_startX + m_endX, m_startY + m_endY)
		
		'// Reset to old colors.
		clrCustom(oldColorR, oldColorG, oldColorB)
	
	end method
	
	'// The url to the image to draw.
	field m_image:string
	
	'// Set this flag to true if you want the shading effect around the image (kind of like a shadow basically).
	field m_shading:byte

end type

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		This is for creating checkboxes.
'// -----------------------------------------------------------------------------------------------------------------
type TCheckbox extends TWindow

	'// Set the state of the checkbox.
	'// 		(int) state: The new state of the checkbox.
	method SetState(state:int); m_state = state; end method
	
	'// Return the current state of the checkbox.
	method GetState:int(); return m_state; end method
	
	'// Draw the checkbox.
	method Draw:byte()
	
		'// Declare some needed variables.
		local oldr:int, oldg:int, oldb:int
		
		'// Set width and length.
		local width:int = m_endX - m_startX
		local height:int = m_endY - m_startY
		
		'// Reset font to default font.
		SetImageFont(defaultFont)
		
		'// Save old colors and set current color to brown.
		clrDarkerBrown()
		oldr = oldColorR
		oldg = oldColorG
		oldb = oldColorB
		
		'// Draw the box
						DrawRect(m_startX + 2, m_startY + 2, width - 4, height - 4) '// Filling
		clrDarkBrown(); 	DrawLine(m_startX, m_startY, m_startX, m_endY - 1)  '// Left margin
						DrawLine(m_startX + 1, m_startY, m_startX + 1, m_endY - 2) '// Left margin
		 				DrawLine(m_startX, m_startY, m_endX - 1, m_startY) '// Upper margin
		  				DrawLine(m_startX, m_startY + 1, m_endX - 2, m_startY + 1) '// Upper margin
		clrBrightBrown();	DrawLine(m_endX - 1, m_startY + 1, m_endX - 1, m_endY - 1)  '// Right margin
						DrawLine(m_endX - 2, m_startY + 2, m_endX - 2, m_endY - 2) '// Right margin
						DrawLine(m_startX + 2, m_endY - 2, m_endX - 1, m_endY - 2) '// Lower margin
						DrawLine(m_startX + 1, m_endY - 1, m_endX - 1, m_endY - 1) '// Lower margin
		
		'// Draw the checkmark.
		if (m_state = CHECKBOX_STATE_CHECKED) then
		
			clrDarkYellow()
			DrawRect(m_startX + 4, m_startY + 4, width - 8, height - 8)
			clrHeadline()
			DrawRect(m_startX + 5, m_startY + 5, width - 10, height - 10)
			clrDarkerBrown()
			Plot(m_startX + 4, m_startY + 4)
			Plot(m_endX - 5, m_endY - 5)
			Plot(m_startX + 4, m_endY - 5)
			Plot(m_endX - 5, m_startY + 4)
		
		end if
		
		'// Reset to old colors.
		clrCustom(oldr, oldg, oldb)
	
	end method
	
	'// The state of the checkbox. It can be one of the following:
	'//		CHECKBOX_STATE_CHECKED = The checkbox is checked.
	'//		CHECKBOX_STATE_UNCHECKED = The checkbox is unchecked.
	field m_state:int

end type

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		This is for creating lists (itemlists).
'// -----------------------------------------------------------------------------------------------------------------
type TItemList extends TWindow

	'// Draw the list.
	method Draw:Byte()
	
		'// Check if the settings of this TWindow are invalid or not.
		if (m_startX > m_endX or m_startY > m_endY or m_columns < 1) ..
			return 0
		
		'// Declare some needed variables.
		local oldr:int, oldg:int, oldb:int
		
		'// Set width and length.
		local width:int = m_endX - m_startX
		local height:int = m_endY - m_startY
		
		'// Reset font to default font.
		SetImageFont(defaultFont)
		
		'// Save old colors and set current color to brown.
		clrDarkerBrown()
		oldr = oldColorR
		oldg = oldColorG
		oldb = oldColorB
		
		'// Draw the list field.
						DrawRect(m_startX + 2, m_startY + 2, width - 4, height - 4) '// Filling
		clrDarkBrown();	DrawLine(m_startX, m_startY, m_startX, m_endY - 1) '// Left margin
						DrawLine(m_startX + 1, m_startY, m_startX + 1, m_endY - 2) '// Left margin
		 				DrawLine(m_startX, m_startY, m_endX - 1, m_startY) '// Upper margin
		  				DrawLine(m_startX, m_startY + 1, m_endX - 2, m_startY + 1) '// Upper margin
		clrBrightBrown();	DrawLine(m_endX - 1, m_startY + 1, m_endX - 1, m_endY - 1) '// Right margin
						DrawLine(m_endX - 2, m_startY + 2, m_endX - 2, m_endY - 2) '// Right margin
						DrawLine(m_startX + 2, m_endY - 2, m_endX - 1, m_endY - 2) '// Lower margin
						DrawLine(m_startX + 1, m_endY - 1, m_endX - 1, m_endY - 1) '// Lower margin
		
		'// Draw list items.
		local row:int = 0
		for local l:string = eachin m_list
		
			'// First item always containes "active", because the server sent it, and we want to know that
			'// it actually got here. So we skip the first item.
			if (m_list.First() = l) ..
				continue
			
			local tempText:TText = new TText
			
			if (m_style = 0) then
			
				if (m_selectedItem = row) then
				
					clrDarkGreen()
					DrawRect(m_startX + 2, m_startY + 2 + 14 * row, width - 4, 15)
				
				end if
				
				for local c:int = 0 until m_columnDataArgument.length
				
					if ((m_columns - 1) < c) ..
						exit
					
					tempText.m_text = str.word(m_columnDataArgument[c], l, KEY_SEMICOLON)
					tempText.m_startX = self.m_startX + m_columnXOffset[c] + 6
					tempText.m_startY = self.m_startY + 2 + 14 * row
					tempText.Draw()
					
					row :+ 1
				
				next
			
			else if (m_style = 1) then
			
				local columnRow = 0
				local yOffset = 2 + 50 * row
				
				if (m_selectedItem = row) then
				
					clrCustom(17, 55, 23)
					DrawRect(m_startX + 4, m_startY + 3 + yOffset, ..
						    width - 10,    6 + 14 * 3)
				
				end if
				
				for local c:int = 0 until m_columnDataArgument.length
				
					if ((m_columns - 1) < c) ..
						exit
					
					select (c)
					
						case 0
							tempText.SetCustomColor(250, 212, 0)
						case 1
							tempText.SetCustomColor(224, 224, 224)
						case 2
							tempText.SetCustomColor(120, 120, 120)
					
					end select
					
					tempText.m_text = str.word(m_columnDataArgument[c], l, KEY_SEMICOLON)
					tempText.m_startX = self.m_startX + 12
					tempText.m_startY = self.m_startY + 4 + 14 * columnRow + yOffset
					tempText.Draw()
					
					columnRow :+ 1
				
				next
				
				row :+ 1
			
			end if
		
		next
		
		'// Reset to old colors.
		clrCustom(oldr, oldg, oldb)
	
	end method
	
	'// The row of the selected item (counting from 0 and up).
	field m_selectedItem:int
	
	'// The linked list that this list represents graphically.
	field m_list:TList
	
	'// Style of the list.
	field m_style:int
	
	'// How many columns there are in the list.
	field m_columns:int = 1
	
	'// Arguments in the string-list are seperated with ';'.
	'// This is an array of which argument each column is going to print.
	field m_columnDataArgument:int[10]
	
	'// This is how far in from m_startX each column is going to be drawn.
	field m_columnXOffset:int[10]

end type

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Add a column to an existing TItemList.
'// 
'// Parameters:
'//		(TInterface) interface: The interface where the layer of the list is contained.
'//		(string) listName: The name of the list to add a column to.
'//		(int) dataArgument: The argument of the data to put in the column.
'//		(int) xOffset: Optional. Default value is 0. How many pixels from the list.m_startX the column should be
'//			drawn.
'// -----------------------------------------------------------------------------------------------------------------
function AddColumnToList(interface:TInterface, listName:string, dataArgument:int, xOffset:int = 0)

	interface.AddColumnToList(listName, dataArgument, xOffset)

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Create an interface object.
'// -----------------------------------------------------------------------------------------------------------------
function CreateInterface:TInterface()

	local interfaceObject:TInterface = new TInterface
	
	'// Every interface starts with 3 fresh layers. You can add more later.
	for local i:int = 1 to 3
		interfaceObject.CreateLayer(i, 0); next
	
	return interfaceObject

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Center mouse.
'// -----------------------------------------------------------------------------------------------------------------
function CenterMouse(); MoveMouse(RES_X / 2, RES_Y / 2); end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Draw an interface and all it's visible gadgets.
'// -----------------------------------------------------------------------------------------------------------------
function DrawInterface(interface:TInterface); interface.Draw(); end function



'                               -----------> User-specified functions <-----------



'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Load fonts to the memory.
'// -----------------------------------------------------------------------------------------------------------------
function loadFonts()

	outLog("Loading fonts to memory.")
	defaultFont   = LoadImageFont("incbin::..\Data\Fonts\Frizqt.ttf",        12, SMOOTHFONT)
	defaultFont2  = LoadImageFont("incbin::..\Data\Fonts\Cour.ttf",          12, SMOOTHFONT)
	defaultFont3  = LoadImageFont("incbin::..\Data\Fonts\Verdana.ttf",       12, SMOOTHFONT)
	headline      = LoadImageFont("incbin::..\Data\Fonts\Frizqt.ttf",        16, SMOOTHFONT)
	meterBar      = LoadImageFont("incbin::..\Data\Fonts\Courbd.ttf",        10, BOLDFONT + SMOOTHFONT)
	verdanaSmall  = LoadImageFont("incbin::..\Data\Fonts\Verdanab.ttf",      12, SMOOTHFONT)
	verdanaMedium = LoadImageFont("incbin::..\Data\Fonts\Verdanab.ttf",      16, BOLDFONT + SMOOTHFONT)
	verdanaBig    = LoadImageFont("incbin::..\Data\Fonts\Verdanab.ttf",      24, BOLDFONT + SMOOTHFONT)

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Load mouse pointer to the memory.
'// -----------------------------------------------------------------------------------------------------------------
function loadMouse()

	outLog("Loading mouse pointer to memory.")
	mousePointer1 = LoadImage("incbin::..\Data\Bitmaps\Interface\MousePointer1.bmp")
	mousePointer1_Black = LoadImage("incbin::..\Data\Bitmaps\Interface\MousePointer1_Black.bmp")

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Draw mouse.
'// -----------------------------------------------------------------------------------------------------------------
function drawMouse(i:int = 0)

	select (i)
	
	 	case MOUSE_POINTER_NORMAL
			SetAlpha(0.4)
			DrawImage(mousePointer1_Black, MouseX() - 1, MouseY() - 1)
			DrawImage(mousePointer1_Black, MouseX() + 1, MouseY() + 1)
			DrawImage(mousePointer1_Black, MouseX() + 1, MouseY())
			SetAlpha(1.0)
			DrawImage(mousePointer1, MouseX(), MouseY())
		case MOUSE_POINTER_LOADING
			SetAlpha(0.4)
			DrawImage(mousePointer1_Black, MouseX() - 1, MouseY() - 1)
			DrawImage(mousePointer1_Black, MouseX() + 1, MouseY() + 1)
			DrawImage(mousePointer1_Black, MouseX() + 1, MouseY())
			SetAlpha(1.0)
			DrawImage(mousePointer1, MouseX(), MouseY())
		default
			SetAlpha(0.4)
			DrawImage(mousePointer1_Black, MouseX() - 1, MouseY() - 1)
			DrawImage(mousePointer1_Black, MouseX() + 1, MouseY() + 1)
			DrawImage(mousePointer1_Black, MouseX() + 1, MouseY())
			SetAlpha(1.0)
			DrawImage(mousePointer1, MouseX(), MouseY())
	
	end select

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Fade out (to black).
'// -----------------------------------------------------------------------------------------------------------------
function fadeOut(t:int)

	local a:float
	
	for local ms:int = 1 to t
	
		a = 0.0 + 1.0 / t * float(ms)
		Cls()
		SetAlpha(1.0)
		drawFrame(Master.in_game)
		SetAlpha(a)
		clrPitchBlack()
		DrawRect(0, 0, 800, 600)
		Flip() 
	
	next
	
	SetAlpha(0.0)

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Fade in (from black).
'// -----------------------------------------------------------------------------------------------------------------
function fadeIn(t:int)

	local a:float
	
	for local ms:int = 1 to t
	
		a = 1.0 - 1.0 / t * float(ms)
		Cls()
		SetAlpha(1.0)
		drawFrame(Master.in_game)
		SetAlpha(a)
		clrPitchBlack()
		DrawRect(0, 0, 800, 600)
		Flip()
	
	next
	
	SetAlpha(1.0)

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Draw current "in-game" frame.
'// -----------------------------------------------------------------------------------------------------------------
function drawFrame_Game()

	clrWhite() '// Reset the color of text's and other manual drawings to white
	drawScreen_Game() '// Draw the interface and stuff
	drawOutput() '// Draw all the output text
	framesThatHavePassed = framesThatHavePassed + 1

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Draw current "login" frame.
'// -----------------------------------------------------------------------------------------------------------------
function drawFrame_Menu()

	clrWhite() '// Reset the color of text's and other manual drawings to white
	drawInterfaces() '// Draw the interfaces
	drawMouse(0) '// Draw the mouse

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Draw the GUI of the main window.
'// -----------------------------------------------------------------------------------------------------------------
function drawScreen_Game()

	local oldr:int, oldg:int, oldb:int', meterPerc:int
	
	SetImageFont(defaultFont)
	clrBrown()
	
	'// Save old colors.
	oldr = oldColorR
	oldg = oldColorG
	oldb = oldColorB
	
	'// Draw the basic interface.
					DrawRect(0, 0, 800, 92) '// Upper bar
	clrDarkBrown();	DrawLine(0, 92, 800, 92)  '// Upper margin
	clrDarkBrown();	DrawLine(0, 93, 800, 93) '// Upper margin
	clrBlack();		DrawLine(0, 94, 800, 94) '// Upper margin
					DrawLine(0, 550, 800, 550) '// Lower margin
	clrBrightBrown();	DrawLine(0, 551, 800, 551) '// Lower margin
	clrBrown();		DrawRect(0, 552, 800, 50) '// Lower bar
	clrBlack();		DrawRect(2, 576, 796, 22) '// Console bar
	clrBrightBrown();	DrawLine(2, 597, 797, 597) '// Console 3d effect
					DrawLine(797, 576, 797, 596) '// Console 3d effect
	clrDarkBrown();	DrawLine(2, 576, 796, 576) '// Console 3d effect
					DrawLine(2, 576, 2, 596) '// Console 3d effect
	
	rem
		drawLocationText() ' temporary
		
		'// Character name
		SetImageFont(verdanaMedium)
		clrDarkBrown()		; DrawText cap(charName), 6, 6
		clrCommon()		; DrawText cap(charName), 5, 5
	end rem
	
	' Health bar
	clrDarkBrown();	DrawLine(5, 30, 107, 30) '// 3d effect
					DrawLine(5, 30, 5, 40) '// 3d effect
	clrBrightBrown();	DrawLine(5, 40, 107, 40) '// 3d effect
					DrawLine(107, 40, 107, 30) '// 3d effect
	clrBlack();		DrawRect(6, 31, 100, 8)
	
	rem
		'// Health meter
		SetImageFont(meterBar)
		if (charCurHealth < 0) ..
			charCurHealth = 0
		meterPerc = int(100.0 * (float(charCurHealth) / float(charMaxHealth)))
		clrBrightGreen()	; DrawRect(6, 31, meterPerc, 8)
		clrGreen()		; DrawRect(6, 32, meterPerc, 7)
		clrDarkGreen()		; DrawText(meterPerc + "%", 61 - Len(meterPerc + "%") * 4, 31)
		clrWhite()		; DrawText(meterPerc + "%", 60 - Len(meterPerc + "%") * 4, 30)
	end rem
	
	' Mana bar
	clrDarkBrown();	DrawLine(5, 42, 107, 42) '// 3d effect
					DrawLine(5, 42, 5, 52) '// 3d effect
	clrBrightBrown();	DrawLine(5, 52, 107, 52) '// 3d effect
					DrawLine(107, 52, 107, 42) '// 3d effect
	clrBlack();		DrawRect(6, 43, 100, 8)
	
	rem
		'// Mana meter
		if (charCurMana < 0) ..
			charCurMana = 0
		meterPerc = int(100.0 * (float(charCurMana) / float(charMaxMana)))
		clrBrightMana()	; DrawRect(6, 43, meterPerc, 8)
		clrMana()			; DrawRect(6, 44, meterPerc, 7)
		clrDarkMana()		; DrawText(meterPerc + "%", 61 - Len(meterPerc + "%") * 4,43)
		clrWhite()		; DrawText(meterPerc + "%", 60 - Len(meterPerc + "%") * 4,42)
		
		'// Rage
		if (charClass = 1) then
			' Rage bar
			clrDarkBrown()		; DrawLine(5, 54, 107, 54) '// 3d effect
							  DrawLine(5, 54, 5, 64) '// 3d effect
			clrBrightBrown()	; DrawLine(5, 64, 107, 64) '// 3d effect
							  DrawLine(107, 64, 107, 54) '// 3d effect
			clrBlack()		; DrawRect(6, 55, 100, 8)
			
			' Rage meter
			meterPerc = Int(100.0 * (Float(charCurRage) / Float(charMaxRage)))
			clrBrightOrange()	; DrawRect 6,55,meterPerc,8
			clrOrange()		; DrawRect 6,56,meterPerc,7
			clrDarkOrange()	; DrawText meterPerc + "%",61 - Len(meterPerc + "%") * 4,55
			clrWhite()		; DrawText meterPerc + "%",60 - Len(meterPerc + "%") * 4,54
			
			' Resting text
			If charResting Then
				SetImageFont(defaultFont3)
				clrDarkBrown()		; DrawText "(Vilar)",20,66
				clrWhite()		; DrawText "(Vilar)",19,65
			End If
			
			' Character level
			SetImageFont(meterBar)
			clrDarkBrown()		; DrawText charLevel,9,68
			clrCommon()		; DrawText charLevel,8,67
		Else
			' Resting text
			If charResting Then
				SetImageFont(defaultFont3)
				clrDarkBrown()		; DrawText "(Vilar)",20,55
				clrWhite()		; DrawText "(Vilar)",19,54
			End If
			
			' Character level
			SetImageFont(meterBar)
			clrDarkBrown()		; DrawText charLevel,9,57
			clrCommon()		; DrawText charLevel,8,56
		End If
	end rem
	
	' Experience bar
	clrDarkBrown();	DrawLine(2, 557, 797, 557) '// 3d effect
					DrawLine(2, 558, 2, 570) '// 3d effect
	clrBrightBrown();	DrawLine(2, 570, 797, 570) '// 3d effect
					DrawLine(797, 557, 797, 570) '// 3d effect
	clrBlack();		DrawRect(3, 558, 794, 12)
	
	rem
		'// Experience meter
		Local meterPerc2:Double
		Local tempPercLen:Double
		Local percLen:Double
		Local lastLevelExp:Double = Double(charLevels(charLevel - 1))
		Local newLevelAt:Double = Double(charLevels(charLevel))
		SetImageFont(meterBar)
		If charLevel = 1 Then
			meterPerc2 = 10000.0 * (Double(charExp - lastLevelExp - 1.0) / Double(newLevelAt - lastLevelExp - 1.0))
			tempPercLen = 794.0 * 0.0001
			percLen = tempPercLen * meterPerc2
			If percLen > 794.0 Then percLen = 794.0
			clrBrightMana()	; DrawRect 3,558,Int(percLen),12
			clrMana()			; DrawRect 3,559,Int(percLen),11
			clrDarkMana	()	; DrawText Int(charExp - lastLevelExp - 1) + "/" + Int(newLevelAt - lastLevelExp - 1),401 - Len(Int(charExp - lastLevelExp - 1) + "/" + Int(newLevelAt - lastLevelExp - 1)) * 4,559
			clrWhite()		; DrawText Int(charExp - lastLevelExp - 1) + "/" + Int(newLevelAt - lastLevelExp - 1),400 - Len(Int(charExp - lastLevelExp - 1) + "/" + Int(newLevelAt - lastLevelExp - 1)) * 4,558
		Else
			meterPerc2 = 10000.0 * (Double(charExp - lastLevelExp) / Double(newLevelAt - lastLevelExp))
			tempPercLen = 794.0 * 0.0001
			percLen = tempPercLen * meterPerc2
			If percLen > 794.0 Then percLen = 794.0
			clrBrightMana()	; DrawRect 3,558,Int(percLen),12
			clrMana()			; DrawRect 3,559,Int(percLen),11
			clrDarkMana()		; DrawText Int(charExp - lastLevelExp) + "/" + Int(newLevelAt - lastLevelExp),401 - Len(Int(charExp - lastLevelExp) + "/" + Int(newLevelAt - lastLevelExp)) * 4,559
			clrWhite()		; DrawText Int(charExp - lastLevelExp) + "/" + Int(newLevelAt - lastLevelExp),400 - Len(Int(charExp - lastLevelExp) + "/" + Int(newLevelAt - lastLevelExp)) * 4,558
		End If
		
		'// Target quick info
		SetImageFont(verdanaMedium)
		If charSelectedObject Then
			Local element:Int = getObjectID(Int(word(0,charSelectedObject,KEY_COLON)))
			Local cat:String = word(1,charSelectedObject,KEY_COLON)
			Local hp:Float,maxhp:Float,sp:Float,maxsp:Float
			
			' Target name
			If cat = "npc" Then
				clrDarkBrown()		; DrawText cap(worldNpcList[element].name),350,6
				clrCommon()		; DrawText cap(worldNpcList[element].name),350,5
			Else If cat = "creature" Then
				clrDarkBrown()		; DrawText cap(worldCreatureList[element].name),350,6
				clrCommon()		; DrawText cap(worldCreatureList[element].name),350,5
			End If
			
			' Health bar
			clrDarkBrown()		; DrawLine 350,30,452,30 '// 3d effect
							  DrawLine 350,30,350,40 '// 3d effect
			clrBrightBrown()	; DrawLine 350,40,452,40 '// 3d effect
							  DrawLine 452,40,452,30 '// 3d effect
			clrBlack()		; DrawRect 351,31,100,8
			
			' Health meter
			SetImageFont(meterBar)
			Local mob:TGNetObject
			If cat = "npc" Then
				mob = getObjectHandle(worldNpcList[element].gid)
				maxhp = worldNpcList[element].maxHealth
			Else If cat = "creature" Then
				mob = getObjectHandle(worldCreatureList[element].gid)
				maxhp = worldCreatureList[element].maxHealth
			End If
			hp = GetGNetInt(mob,MOB_SLOT_HEALTH)
			If hp Then
				meterPerc = Int(100.0 * (hp / maxhp))
			Else
				meterPerc = 0
			End If
			clrBrightGreen()	; DrawRect 351,31,meterPerc,8
			clrGreen()		; DrawRect 351,32,meterPerc,7
			clrDarkGreen()		; DrawText meterPerc + "%",411 - Len(meterPerc + "%") * 4,31
			clrWhite()		; DrawText meterPerc + "%",410 - Len(meterPerc + "%") * 4,30
			
			' Mana bar
			clrDarkBrown()		; DrawLine 350,42,452,42 '// 3d effect
							  DrawLine 350,42,350,52 '// 3d effect
			clrBrightBrown()	; DrawLine 350,52,452,52 '// 3d effect
							  DrawLine 452,52,452,42 '// 3d effect
			clrBlack()		; DrawRect 351,43,100,8
			
			' Mana meter
			sp = Float(GetGNetInt(mob,MOB_SLOT_MANA))
			If cat = "npc" Then
				maxsp = Float(worldNpcList[element].maxMana)
			Else If cat = "creature" Then
				maxsp = Float(worldCreatureList[element].maxMana)
			End If
			If sp Then
				meterPerc = Int(100.0 * (sp / maxsp))
			Else
				meterPerc = 0
			End If
			clrBrightMana()	; DrawRect 351,43,meterPerc,8
			clrMana()			; DrawRect 351,44,meterPerc,7
			clrDarkMana()		; DrawText meterPerc + "%",411 - Len(meterPerc + "%") * 4,43
			clrWhite()		; DrawText meterPerc + "%",410 - Len(meterPerc + "%") * 4,42
		End If
	end rem
	
	'// Draw the console-input
	SetImageFont(defaultFont) 
	clrBrightGreen()
	DrawText("> " + conInputText, 5, 579) 
	
	rem
		'// Draw mini-map
		drawMiniMap()
		
		'// Draw the location text above the mini-map
		SetImageFont verdanaSmall
		clrBrightGreen(); DrawText charSubLocation,700,2
	end rem
	
	'// Reset to old colors
	clrCustom(oldr, oldg, oldb)

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Draw all the visible interfaces.
'// -----------------------------------------------------------------------------------------------------------------
function drawInterfaces()

	for local ui:TInterface = eachin interfaceList
		DrawInterface(ui); next
	
end function
